package com.xc.common.tool;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.AuthSchemes;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class HttpUtil {
	public static Map<String,String> getRequestParams(HttpServletRequest request) {
		Map<String,String> paramMap = new HashMap<>();
		Enumeration<String> paramNames = request.getParameterNames();
		while (paramNames.hasMoreElements()) {
			String key = (String) paramNames.nextElement();
			String value = request.getParameter(key);
			paramMap.put(key, value);
		}
		return paramMap;
	}
	public static Map<String,Object> isRemoteParamsOk(Map<String,Object> params){
		Map<String,Object> data = new HashMap<>();
		Map<String,Object> jobj = newResponseData(data,"0","获取Token成功");
		Object timestamp = params.get("timestamp");
		Object machineNo = params.get("machineNo");
		Object accessToken = params.get("accessToken");
		Object sign = params.get("sign");
		if(accessToken==null){
			jobj = newResponseData(null,"1001","accessToken不能为空");
			return jobj;  
		}
		if(machineNo==null){
			jobj = newResponseData(null,"1001","machine_no不能为空");
			return jobj;  
		}
		if(timestamp==null){
			jobj = newResponseData(null,"1001","timestamp不能为空");
			return jobj;  
		}
		if(sign==null){
    		jobj = newResponseData(null,"1001","sign不能为空");
    		return jobj;  
    	}
		return jobj;
	}
	public static Map<String,Object> isRemoteParamsOk2(Map<String,Object> params){
		Map<String,Object> data = new HashMap<>();
		Map<String,Object> jobj = newResponseData(data,"0","获取Token成功");
		
		Object timestamp = params.get("timestamp");
		
		Object machineNo = params.get("machineNo");
		Object sign = params.get("sign");
		if(machineNo==null){
			jobj = newResponseData(null,"1001","machine_no不能为空");
			return jobj;  
		}
		if(timestamp==null){
			jobj = newResponseData(null,"1001","timestamp不能为空");
			return jobj;  
		}
		Long mills = System.currentTimeMillis();
		String ts = timestamp.toString();
		if(!StringUtils.isNumeric(ts)||ts.indexOf("-")!=-1||ts.indexOf(".")!=-1) {
			jobj = newResponseData(null,"1001","timestamp只能为正整数");
			return jobj;  
		}
		long gap = mills-Long.valueOf(timestamp.toString());
		if(gap>1000044) {
			jobj = newResponseData(null,"1001","timestamp必须取当前时间");
			return jobj;  
		}
		if(sign==null){
			jobj = newResponseData(null,"1001","sign不能为空");
			return jobj;  
		}
		return jobj;
	}
	public static Map<String,Object> newResponseData(Map<String,Object> data,String errcode,String msg) {
		Map<String,Object> jobj = new HashMap<>();
    	jobj.put("code", errcode);
    	jobj.put("data", data);
    	jobj.put("msg", msg);
		return jobj;
	}
	public static List<String> getRequestParamKeys(HttpServletRequest request) {
		List<String> keys = Lists.newArrayList();
		@SuppressWarnings("rawtypes")
		Enumeration paramNames = request.getParameterNames();
		while (paramNames.hasMoreElements()) {
			String key = (String) paramNames.nextElement();
			keys.add(key);
		}
		Ordering<String> ordering = Ordering.natural();
		keys = ordering.sortedCopy(keys);
		return keys;
	}

	public static String joinSign(String serectKey, JSONObject jobj, HttpServletRequest request) {
		StringBuilder buf = new StringBuilder(serectKey);
		List<String> keys = getRequestParamKeys(request);
		for (String key : keys) {
			buf.append(key).append(jobj.getString(key));
		}
		buf.append(serectKey);
		String str = YYMD5.hashToHexString(buf.toString().toLowerCase());
		return str;
	}

	public static Date strToDate(String strDate) {
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
		ParsePosition pos = new ParsePosition(0);
		Date strtodate = formatter.parse(strDate, pos);
		return strtodate;
	}

	public static HttpResponse doPost(String host, String path, Map<String, String> headers, Map<String, String> querys,
			JSONObject bodys) throws Exception {
		HttpClient httpClient = wrapClient(host, path);
		String addr = buildUrl(host, path, querys);
		HttpPost request = new HttpPost(addr);
		for (Map.Entry<String, String> e : headers.entrySet()) {
			request.addHeader(e.getKey(), e.getValue());
		}
		StringEntity entity = new StringEntity(bodys.toString(),"UTF-8");
        entity.setContentType("application/json");
        request.setEntity(entity);
		return httpClient.execute(request);
	}
	public static HttpResponse doPost(String host, String path, Map<String, String> headers, Map<String, String> querys,
			Map<String,String> bodys) throws Exception {
		HttpClient httpClient = wrapClient(host, path);
		String addr = buildUrl(host, path, querys);
		HttpPost request = new HttpPost(addr);
		for (Map.Entry<String, String> e : headers.entrySet()) {
			request.addHeader(e.getKey(), e.getValue());
		}
		StringEntity entity = new StringEntity(JSON.toJSONString(bodys),"UTF-8");//
		entity.setContentType("application/json");
		request.setEntity(entity);
		return httpClient.execute(request);
	}

	public static HttpClient wrapClient(String host, String path) {
		HttpClient httpClient = HttpClientBuilder.create().build();
		if (host != null && host.startsWith("https://")) {
			return createSslClient();
		} else if (StringUtils.isBlank(host) && path != null && path.startsWith("https://")) {
			return createSslClient();
		}
		return httpClient;
	}

	public static String buildUrl(String host, String path, Map<String, String> querys)
			throws UnsupportedEncodingException {
		StringBuilder sbUrl = new StringBuilder();
		if (!StringUtils.isBlank(host)) {
			sbUrl.append(host);
		}
		if (!StringUtils.isBlank(path)) {
			sbUrl.append(path);
		}
		if (null != querys) {
			StringBuilder sbQuery = new StringBuilder();
			for (Map.Entry<String, String> query : querys.entrySet()) {
				if (0 < sbQuery.length()) {
					sbQuery.append("&");
				}
				if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {
					sbQuery.append(query.getValue());
				}
				if (!StringUtils.isBlank(query.getKey())) {
					sbQuery.append(query.getKey());
					if (!StringUtils.isBlank(query.getValue())) {
						sbQuery.append("=");
						sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));
					}
				}
			}
			if (0 < sbQuery.length()) {
				sbUrl.append("?").append(sbQuery);
			}
		}
		return sbUrl.toString();
	}

	public static HttpClient createSslClient() {
		try {
			// 在调用SSL之前需要重写验证方法，取消检测SSL
			X509TrustManager trustManager = new X509TrustManager() {
				@Override
				public X509Certificate[] getAcceptedIssuers() {
					return null;
				}

				@Override
				public void checkClientTrusted(X509Certificate[] xcs, String str) {
				}

				public void checkServerTrusted(X509Certificate[] xcs, String str) {
				}
			};
			SSLContext ctx = SSLContext.getInstance(SSLConnectionSocketFactory.TLS);
			ctx.init(null, new TrustManager[] { trustManager }, null);
			SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(ctx,
					NoopHostnameVerifier.INSTANCE);
			// 创建Registry
			RequestConfig requestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD_STRICT)
					.setExpectContinueEnabled(Boolean.TRUE)
					.setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST))
					.setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC)).build();
			Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
					.register("http", PlainConnectionSocketFactory.INSTANCE).register("https", socketFactory).build();
			// 创建ConnectionManager，添加Connection配置信息
			PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(
					socketFactoryRegistry);
			CloseableHttpClient closeableHttpClient = HttpClients.custom().setConnectionManager(connectionManager)
					.setDefaultRequestConfig(requestConfig).build();
			return closeableHttpClient;
		} catch (KeyManagementException ex) {
			throw new RuntimeException(ex);
		} catch (NoSuchAlgorithmException ex) {
			throw new RuntimeException(ex);
		}
	}
	public static String getIpAdrress(HttpServletRequest request) {
        String Xip = request.getHeader("X-Real-IP");
        String XFor = request.getHeader("X-Forwarded-For");
        if(StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)){
            //多次反向代理后会有多个ip值，第一个ip才是真实ip
            int index = XFor.indexOf(",");
            if(index != -1){
                return XFor.substring(0,index);
            }else{
                return XFor;
            }
        }
        XFor = Xip;
        if(StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)){
            return XFor;
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("HTTP_CLIENT_IP");
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getRemoteAddr();
        }
        return XFor;
    }
}
